import { computed, defineComponent, h, provide } from 'vue';
import { useIsMounted } from 'vooks';
import { depx } from 'seemly';
import { ChevronLeftIcon, ChevronRightIcon } from '../../_internal/icons';
import { NBaseIcon } from '../../_internal';
import { NButton } from '../../button';
import { useLocale, useFormItem, useTheme, useConfig } from '../../_mixins';
import { createKey } from '../../_utils/cssr';
import { warn, call } from '../../_utils';
import { transferLight } from '../styles';
import NTransferHeader from './TransferHeader';
import NTransferList from './TransferList';
import NTransferFilter from './TransferFilter';
import { useTransferData } from './use-transfer-data';
import style from './styles/index.cssr';
import { transferInjectionKey } from './interface';
const transferProps = Object.assign(Object.assign({}, useTheme.props), { value: Array, defaultValue: {
        type: Array,
        default: null
    }, options: {
        type: Array,
        default: () => []
    }, disabled: {
        type: Boolean,
        default: undefined
    }, virtualScroll: Boolean, sourceTitle: String, targetTitle: String, filterable: Boolean, sourceFilterPlaceholder: String, targetFilterPlaceholder: String, filter: {
        type: Function,
        default: (pattern, option) => {
            if (!pattern)
                return true;
            return ~('' + option.label)
                .toLowerCase()
                .indexOf(('' + pattern).toLowerCase());
        }
    }, size: String, 'onUpdate:value': [Function, Array], onUpdateValue: [Function, Array], onChange: {
        type: [Function, Array],
        validator: () => {
            if (process.env.NODE_ENV !== 'production') {
                warn('transfer', '`on-change` is deprecated, please use `on-update:value` instead.');
            }
            return true;
        },
        default: undefined
    } });
export default defineComponent({
    name: 'Transfer',
    props: transferProps,
    setup(props) {
        const { mergedClsPrefixRef } = useConfig(props);
        const themeRef = useTheme('Transfer', 'Transfer', style, transferLight, props, mergedClsPrefixRef);
        const formItem = useFormItem(props);
        const { mergedSizeRef, mergedDisabledRef } = formItem;
        const itemSizeRef = computed(() => {
            const { value: size } = mergedSizeRef;
            const { self: { [createKey('itemHeight', size)]: itemSize } } = themeRef.value;
            return depx(itemSize);
        });
        const { uncontrolledValue: uncontrolledValueRef, mergedValue: mergedValueRef, avlSrcValueSet: avlSrcValueSetRef, avlTgtValueSet: avlTgtValueSetRef, tgtOpts: tgtOptsRef, srcOpts: srcOptsRef, filteredSrcOpts: filteredSrcOptsRef, filteredTgtOpts: filteredTgtOptsRef, srcCheckedValues: srcCheckedValuesRef, tgtCheckedValues: tgtCheckedValuesRef, srcCheckedStatus: srcCheckedStatusRef, tgtCheckedStatus: tgtCheckedStatusRef, srcPattern: srcPatternRef, tgtPattern: tgtPatternRef, isInputing: isInputingRef, fromButtonDisabled: fromButtonDisabledRef, toButtonDisabled: toButtonDisabledRef, handleInputFocus, handleInputBlur, handleTgtFilterUpdateValue, handleSrcFilterUpdateValue } = useTransferData(props, mergedDisabledRef);
        function doUpdateValue(value) {
            const { onUpdateValue, 'onUpdate:value': _onUpdateValue, onChange } = props;
            const { nTriggerFormInput, nTriggerFormChange } = formItem;
            if (onUpdateValue)
                call(onUpdateValue, value);
            if (_onUpdateValue)
                call(_onUpdateValue, value);
            if (onChange)
                call(onChange, value);
            uncontrolledValueRef.value = value;
            nTriggerFormInput();
            nTriggerFormChange();
        }
        function handleSrcHeaderCheck(value) {
            const { value: { checked, indeterminate } } = srcCheckedStatusRef;
            if (indeterminate || checked) {
                srcCheckedValuesRef.value = [];
            }
            else {
                srcCheckedValuesRef.value = Array.from(avlSrcValueSetRef.value);
            }
        }
        function handleTgtHeaderCheck() {
            const { value: { checked, indeterminate } } = tgtCheckedStatusRef;
            if (indeterminate || checked) {
                tgtCheckedValuesRef.value = [];
            }
            else {
                tgtCheckedValuesRef.value = Array.from(avlTgtValueSetRef.value);
            }
        }
        function handleTgtCheckboxClick(checked, optionValue) {
            if (checked) {
                tgtCheckedValuesRef.value.push(optionValue);
            }
            else {
                const index = tgtCheckedValuesRef.value.findIndex((v) => v === optionValue);
                if (~index) {
                    tgtCheckedValuesRef.value.splice(index, 1);
                }
            }
        }
        function handleSrcCheckboxClick(checked, optionValue) {
            if (checked) {
                srcCheckedValuesRef.value.push(optionValue);
            }
            else {
                const index = srcCheckedValuesRef.value.findIndex((v) => v === optionValue);
                if (~index) {
                    srcCheckedValuesRef.value.splice(index, 1);
                }
            }
        }
        function handleToTgtClick() {
            doUpdateValue(srcCheckedValuesRef.value.concat(mergedValueRef.value || []));
            srcCheckedValuesRef.value = [];
        }
        function handleToSrcClick() {
            const tgtCheckedValueSet = new Set(tgtCheckedValuesRef.value);
            doUpdateValue((mergedValueRef.value || []).filter((v) => !tgtCheckedValueSet.has(v)));
            tgtCheckedValuesRef.value = [];
        }
        provide(transferInjectionKey, {
            mergedClsPrefixRef,
            mergedSizeRef,
            disabledRef: mergedDisabledRef,
            mergedThemeRef: themeRef,
            srcCheckedValuesRef,
            tgtCheckedValuesRef,
            srcOptsRef,
            tgtOptsRef,
            srcCheckedStatusRef,
            tgtCheckedStatusRef,
            handleSrcCheckboxClick,
            handleTgtCheckboxClick
        });
        const { localeRef } = useLocale('Transfer');
        return {
            locale: localeRef,
            mergedClsPrefix: mergedClsPrefixRef,
            mergedDisabled: mergedDisabledRef,
            itemSize: itemSizeRef,
            isMounted: useIsMounted(),
            isInputing: isInputingRef,
            mergedTheme: themeRef,
            filteredSrcOpts: filteredSrcOptsRef,
            filteredTgtOpts: filteredTgtOptsRef,
            srcPattern: srcPatternRef,
            tgtPattern: tgtPatternRef,
            toButtonDisabled: toButtonDisabledRef,
            fromButtonDisabled: fromButtonDisabledRef,
            handleSrcHeaderCheck,
            handleTgtHeaderCheck,
            handleToSrcClick,
            handleToTgtClick,
            handleInputFocus,
            handleInputBlur,
            handleTgtFilterUpdateValue,
            handleSrcFilterUpdateValue,
            cssVars: computed(() => {
                const { value: size } = mergedSizeRef;
                const { common: { cubicBezierEaseInOut, cubicBezierEaseIn, cubicBezierEaseOut }, self: { width, borderRadius, borderColor, listColor, headerColor, titleTextColor, titleTextColorDisabled, extraTextColor, filterDividerColor, itemTextColor, itemColorPending, itemTextColorDisabled, extraFontSize, titleFontWeight, iconColor, iconColorDisabled, [createKey('fontSize', size)]: fontSize, [createKey('itemHeight', size)]: itemHeight } } = themeRef.value;
                return {
                    '--bezier': cubicBezierEaseInOut,
                    '--bezier-ease-in': cubicBezierEaseIn,
                    '--bezier-ease-out': cubicBezierEaseOut,
                    '--border-color': borderColor,
                    '--border-radius': borderRadius,
                    '--extra-font-size': extraFontSize,
                    '--filter-divider-color': filterDividerColor,
                    '--font-size': fontSize,
                    '--header-color': headerColor,
                    '--header-extra-text-color': extraTextColor,
                    '--header-font-weight': titleFontWeight,
                    '--header-text-color': titleTextColor,
                    '--header-text-color-disabled': titleTextColorDisabled,
                    '--item-color-pending': itemColorPending,
                    '--item-height': itemHeight,
                    '--item-text-color': itemTextColor,
                    '--item-text-color-disabled': itemTextColorDisabled,
                    '--list-color': listColor,
                    '--width': width,
                    '--icon-color': iconColor,
                    '--icon-color-disabled': iconColorDisabled
                };
            })
        };
    },
    render() {
        const { mergedClsPrefix } = this;
        return (h("div", { class: [
                `${mergedClsPrefix}-transfer`,
                this.mergedDisabled && `${mergedClsPrefix}-transfer--disabled`,
                this.filterable && `${mergedClsPrefix}-transfer--filterable`
            ], style: this.cssVars },
            h("div", { class: `${mergedClsPrefix}-transfer-list` },
                h(NTransferHeader, { source: true, onChange: this.handleSrcHeaderCheck, title: this.sourceTitle || this.locale.sourceTitle }),
                h("div", { class: `${mergedClsPrefix}-transfer-list-body` },
                    this.filterable ? (h(NTransferFilter, { onUpdateValue: this.handleSrcFilterUpdateValue, value: this.srcPattern, disabled: this.mergedDisabled, placeholder: this.sourceFilterPlaceholder, onFocus: this.handleInputFocus, onBlur: this.handleInputBlur })) : null,
                    h("div", { class: `${mergedClsPrefix}-transfer-list-flex-container` },
                        h(NTransferList, { source: true, options: this.filteredSrcOpts, disabled: this.mergedDisabled, virtualScroll: this.virtualScroll, isMounted: this.isMounted, isInputing: this.isInputing, itemSize: this.itemSize }))),
                h("div", { class: `${mergedClsPrefix}-transfer-list__border` })),
            h("div", { class: `${mergedClsPrefix}-transfer-gap` },
                h(NButton, { disabled: this.toButtonDisabled || this.mergedDisabled, theme: this.mergedTheme.peers.Button, themeOverrides: this.mergedTheme.peerOverrides.Button, onClick: this.handleToTgtClick }, {
                    icon: () => (h(NBaseIcon, { clsPrefix: mergedClsPrefix }, { default: () => h(ChevronRightIcon, null) }))
                }),
                h(NButton, { disabled: this.fromButtonDisabled || this.mergedDisabled, theme: this.mergedTheme.peers.Button, themeOverrides: this.mergedTheme.peerOverrides.Button, onClick: this.handleToSrcClick }, {
                    icon: () => (h(NBaseIcon, { clsPrefix: mergedClsPrefix }, { default: () => h(ChevronLeftIcon, null) }))
                })),
            h("div", { class: `${mergedClsPrefix}-transfer-list` },
                h(NTransferHeader, { onChange: this.handleTgtHeaderCheck, title: this.targetTitle || this.locale.targetTitle }),
                h("div", { class: `${mergedClsPrefix}-transfer-list-body` },
                    this.filterable ? (h(NTransferFilter, { onUpdateValue: this.handleTgtFilterUpdateValue, value: this.tgtPattern, disabled: this.mergedDisabled, placeholder: this.targetFilterPlaceholder, onFocus: this.handleInputFocus, onBlur: this.handleInputBlur })) : null,
                    h("div", { class: `${mergedClsPrefix}-transfer-list-flex-container` },
                        h(NTransferList, { options: this.filteredTgtOpts, disabled: this.mergedDisabled, virtualScroll: this.virtualScroll, isMounted: this.isMounted, isInputing: this.isInputing, itemSize: this.itemSize }))),
                h("div", { class: `${mergedClsPrefix}-transfer-list__border` }))));
    }
});
